package org.example.batch;

import org.apache.commons.lang3.StringUtils;
import org.example.domain.StudentProcessed;
import org.example.mapper.StudentProcessedMapper;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * MyBatis版本的学生数据写入器
 * 
 * 使用MyBatis进行批量数据写入，演示Spring Batch与MyBatis的集成
 * 
 * 主要功能：
 * 1. 批量数据库写入（使用MyBatis的批量插入）
 * 2. 数据分类统计和分析
 * 3. 写入性能监控
 * 4. 错误处理和日志记录
 * 
 * @author Spring Batch + MyBatis Demo
 */

public class MyBatisStudentWriter implements ItemWriter<StudentProcessed> {
    
    @Autowired
    private StudentProcessedMapper studentProcessedMapper;
    
    // 静态统计信息
    private static long totalWrittenRecords = 0;
    private static long totalWrittenBatches = 0;
    private static long totalWriteTime = 0;
    
    @Override
    public void write(List<? extends StudentProcessed> items) throws Exception {
        
        if (items == null || items.isEmpty()) {
            return;
        }
        
        long batchStartTime = System.currentTimeMillis();
        
        System.out.println("\n💾 MyBatis批量写入开始");
        System.out.println("=========================================");
        System.out.println("📊 批次信息:");
        System.out.println("  批次大小: " + items.size() + " 条记录");
        
        try {
            // === 数据分类统计 ===
            analyzeDataDistribution(items);
            
            // === 执行批量写入 ===
            List<StudentProcessed> records = items.stream()
                .map(item -> (StudentProcessed) item)
                .collect(Collectors.toList());
            
            // 使用MyBatis批量插入
            int insertedCount = studentProcessedMapper.batchInsert(records);
            
            // === 更新统计信息 ===
            totalWrittenRecords += insertedCount;
            totalWrittenBatches++;
            
            // === 性能统计 ===
            long batchEndTime = System.currentTimeMillis();
            long batchDuration = batchEndTime - batchStartTime;
            totalWriteTime += batchDuration;
            
            double recordsPerSecond = batchDuration > 0 ? items.size() * 1000.0 / batchDuration : 0;
            
            System.out.println("\n✅ 批量写入结果:");
            System.out.println("  成功写入: " + insertedCount + " 条记录");
            System.out.println("  写入耗时: " + batchDuration + " ms");
            System.out.println("  写入性能: " + String.format("%.2f", recordsPerSecond) + " 记录/秒");
            
            // === 显示部分写入记录 ===
            displaySampleRecords(records);
            
            System.out.println("=========================================");
            System.out.println("💾 MyBatis批量写入完成\n");
            
        } catch (Exception e) {
            System.err.println("❌ MyBatis批量写入失败: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }
    
    /**
     * 分析数据分布
     */
    private void analyzeDataDistribution(List<? extends StudentProcessed> items) {
        
        // 按年龄分类统计
        Map<String, Long> ageCategoryStats = items.stream()
            .collect(Collectors.groupingBy(
                item -> item.getAgeCategory() != null ? item.getAgeCategory() : "未知",
                Collectors.counting()
            ));
        
        // 按性别统计
        Map<String, Long> genderStats = items.stream()
            .collect(Collectors.groupingBy(
                item -> item.getGender() != null ? item.getGender() : "U",
                Collectors.counting()
            ));
        
        // 按处理状态统计
        Map<String, Long> statusStats = items.stream()
            .collect(Collectors.groupingBy(
                item -> item.getProcessStatus() != null ? item.getProcessStatus() : "UNKNOWN",
                Collectors.counting()
            ));
        
        // 数据质量统计
        double avgQualityScore = items.stream()
            .mapToInt(item -> item.getQualityScore() != null ? item.getQualityScore() : 0)
            .average()
            .orElse(0.0);
        
        long highQualityCount = items.stream()
            .mapToInt(item -> item.getQualityScore() != null ? item.getQualityScore() : 0)
            .filter(score -> score >= 80)
            .count();
        
        // 输出统计信息
        System.out.println("📈 数据分布分析:");
        
        System.out.println("  年龄分类:");
        ageCategoryStats.forEach((category, count) -> 
            System.out.println("    " + category + ": " + count + " 人"));
        
        System.out.println("  性别分布:");
        genderStats.forEach((gender, count) -> {
            String genderName = "M".equals(gender) ? "男" : "F".equals(gender) ? "女" : "未知";
            System.out.println("    " + genderName + ": " + count + " 人");
        });
        
        System.out.println("  处理状态:");
        statusStats.forEach((status, count) -> 
            System.out.println("    " + status + ": " + count + " 条"));
        
        System.out.println("  数据质量:");
        System.out.println("    平均质量评分: " + String.format("%.1f", avgQualityScore) + " 分");
        System.out.println("    高质量数据: " + highQualityCount + " 条 (≥80分)");
        System.out.println("    质量达标率: " + String.format("%.1f%%", 
            highQualityCount * 100.0 / items.size()));
    }
    
    /**
     * 显示部分写入记录
     */
    private void displaySampleRecords(List<StudentProcessed> records) {
        
        System.out.println("\n📝 写入记录示例:");
        
        // 显示前3条记录
        for (int i = 0; i < Math.min(3, records.size()); i++) {
            StudentProcessed record = records.get(i);
            System.out.println("  " + (i + 1) + ". ID:" + record.getSourceStudentId() + 
                             " | 姓名:" + record.getProcessedName() + 
                             " | 年龄:" + record.getAge() + 
                             " | 分类:" + record.getAgeCategory() +
                             " | 质量:" + record.getQualityScore() + "分");
        }
        
        // 如果记录数超过6条，显示省略信息和后3条
        if (records.size() > 6) {
            System.out.println("  ... (省略中间 " + (records.size() - 6) + " 条记录) ...");
            
            for (int i = records.size() - 3; i < records.size(); i++) {
                StudentProcessed record = records.get(i);
                System.out.println("  " + (i + 1) + ". ID:" + record.getSourceStudentId() + 
                                 " | 姓名:" + record.getProcessedName() + 
                                 " | 年龄:" + record.getAge() + 
                                 " | 分类:" + record.getAgeCategory() +
                                 " | 质量:" + record.getQualityScore() + "分");
            }
        } else if (records.size() > 3) {
            // 显示剩余的记录
            for (int i = 3; i < records.size(); i++) {
                StudentProcessed record = records.get(i);
                System.out.println("  " + (i + 1) + ". ID:" + record.getSourceStudentId() + 
                                 " | 姓名:" + record.getProcessedName() + 
                                 " | 年龄:" + record.getAge() + 
                                 " | 分类:" + record.getAgeCategory() +
                                 " | 质量:" + record.getQualityScore() + "分");
            }
        }
    }
    
    /**
     * 获取写入统计信息
     */
    public static Map<String, Object> getWriteStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalWrittenRecords", totalWrittenRecords);
        stats.put("totalWrittenBatches", totalWrittenBatches);
        stats.put("totalWriteTime", totalWriteTime);
        stats.put("avgBatchSize", totalWrittenBatches > 0 ? totalWrittenRecords / totalWrittenBatches : 0);
        stats.put("avgWriteSpeed", totalWriteTime > 0 ? totalWrittenRecords * 1000.0 / totalWriteTime : 0);
        return stats;
    }
    
    /**
     * 重置写入统计信息
     */
    public static void resetStatistics() {
        totalWrittenRecords = 0;
        totalWrittenBatches = 0;
        totalWriteTime = 0;
        System.out.println("🔄 MyBatis写入器统计信息已重置");
    }
    
    /**
     * 打印详细统计信息
     */
    public static void printDetailedStatistics() {
        System.out.println("\n💾 MyBatis写入器统计信息");
        System.out.println(StringUtils.repeat("-",30));
        System.out.println("总写入记录数: " + totalWrittenRecords);
        System.out.println("总写入批次数: " + totalWrittenBatches);
        System.out.println("总写入耗时: " + totalWriteTime + " ms");
        
        if (totalWrittenBatches > 0) {
            System.out.println("平均批次大小: " + (totalWrittenRecords / totalWrittenBatches) + " 条/批次");
        }
        
        if (totalWriteTime > 0) {
            double avgSpeed = totalWrittenRecords * 1000.0 / totalWriteTime;
            System.out.println("平均写入速度: " + String.format("%.2f", avgSpeed) + " 记录/秒");
        }

        System.out.println(StringUtils.repeat("-",30));
    }
}
